use m3u8_rs::{MasterPlaylist, MediaPlaylist, Playlist};

use crate::{
    m3u8_key::{download_key, Key},
    utils::parse_m3u8_url_get_host_and_baseurl,
};

/// 根据url解析出播放列表
pub async fn get_ts_list_and_key(url: &str) -> Result<(Vec<String>, Key), String> {

    let m3u8_resp = reqwest::get(url.clone()).await ;
    if m3u8_resp.is_err(){
        let err = format!("{url} 访问失败:{}" , m3u8_resp.err().unwrap().to_string() );
        return Err(err)
    }

    let Ok(m3u8_data) = m3u8_resp.unwrap().bytes().await else {  return Err("m3u8 数据读取失败".to_string())   } ;

    let Ok(playlist)  = m3u8_rs::parse_playlist_res(&m3u8_data) else { return Err("播放列表解析失败".to_string()) };

    let (host, base_url) = parse_m3u8_url_get_host_and_baseurl(url.clone()).unwrap();

    let ts_list = match playlist {
        Playlist::MasterPlaylist(master) => parse_master_play_list(&host, &base_url, &master).await,
        Playlist::MediaPlaylist(media) => parse_media_play_list(&host, &base_url, &media).await,
    };

    Ok(ts_list)
}

/// 解析出播放列表
async fn parse_master_play_list(
    host: &str,
    base_url: &str,
    playlist: &MasterPlaylist,
) -> (Vec<String>, Key) {
    let var_stream = playlist.variants.get(0).unwrap();
    let _uri = var_stream.uri.clone();

    let m3u8_url = if _uri.starts_with("/") {
        format!("{}{}", host.clone(), _uri.clone())
    } else {
        format!("{}{}", base_url.clone(), _uri.clone())
    };

    println!("MasterPlaylist中,需要下载 {m3u8_url} ");

    let m3u8_resp_res = reqwest::get(m3u8_url.clone()).await;

    if m3u8_resp_res.is_err() {
        eprintln!("{m3u8_url} 访问失败: {:?}", m3u8_resp_res.err());
        panic!("EXIT");
    }

    let Ok(m3u8_data) = m3u8_resp_res.unwrap().bytes().await else { panic!("m3u8 数据读取失败")} ;
    let parsed = m3u8_rs::parse_playlist_res(&m3u8_data);

    let Ok(playlist) = parsed else { panic!("解析失败") };

    match playlist {
        Playlist::MasterPlaylist(_master) => {
            panic!("解析失败: master套娃...")
        }
        Playlist::MediaPlaylist(pl) => {
            // 需要重新设置 base_url
            let (_, base_url) = parse_m3u8_url_get_host_and_baseurl(&m3u8_url).unwrap();

            parse_media_play_list(&host, &base_url, &pl).await
        }
    }
}

/// 解析出播放列表
async fn parse_media_play_list(
    host: &str,
    base_url: &str,
    playlist: &MediaPlaylist,
) -> (Vec<String>, Key) {
    let _key = playlist
        .segments
        .clone()
        .iter()
        .find(|it| it.key.is_some())
        .map(|seg| seg.key.clone().unwrap());

    let key = if _key.is_some() {
        download_key(&_key.unwrap(), base_url).await
    } else {
        Key::default()
    };

    let url_list = playlist
        .segments
        .iter()
        .map(|it| {
            let uri = it.uri.clone();
            if uri.starts_with("http") {
                return uri;
            }
            if uri.starts_with("/") {
                let url = host.to_string() + &uri;
                return url;
            }
            return base_url.to_string() + &uri;
        })
        .collect::<Vec<_>>();

    (url_list, key)
}

#[cfg(test)]
mod _test {
    use super::get_ts_list_and_key;

    #[tokio::test]
    async fn test_get_ts_list_and_key() {
        let m3u8_url = "https://hd.lz-cdn18.com/20230202/336_f151c67e/2000k/hls/mixed.m3u8";
        let res = get_ts_list_and_key(m3u8_url).await;
        println!("{res:#?}");
    }
}
